package com.yami.shop.admin.controller;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.util.MapUtils;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.enums.UserFundDetailEnum;
import com.yami.shop.bean.model.*;
import com.yami.shop.bean.param.GetVipLevel3UserPerformanceParam;
import com.yami.shop.bean.vo.BranchUserCashOutStatisticsVo;
import com.yami.shop.bean.vo.GetVipLevel3UserPerformanceVo;
import com.yami.shop.bean.vo.UserFundDetailVo;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.service.*;
import jakarta.servlet.http.HttpServletResponse;
import jodd.util.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 财务统计
 */
@RestController
@RequestMapping("/order/financeStatistics")
public class FinanceStatisticsController {
    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderItemService orderItemService;

    @Autowired
    private OrderRefundService orderRefundService;
    @Autowired
    private UserFundDetailService userFundDetailService;

    @Autowired
    private UserService userService;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private UserCashOutService userCashOutService;

    /**
     * 订单和奖励金额的统计
     * @param type
     * @return
     */
    @PreAuthorize("@pms.hasPermission('order:order:page')")
    @GetMapping("/getOrderStatistics")
    public ServerResponseEntity<Map<String,Object>> getOrderStatistics(Integer type) {
        Map<String,Object> rmap=new HashMap<>();
        if(type == null){
            type =0;
        }
        Date date = new Date();
        DateTime startTime=null;
        DateTime endTime=null;
        if(type == 0){
            //查询当天
            startTime = DateUtil.beginOfDay(date);
            endTime = DateUtil.endOfDay(date);
        }else if(type == 1){
            //当周
            startTime = DateUtil.beginOfWeek(date);
            endTime = DateUtil.endOfWeek(date);
        }else if(type == 2){
            //当月
            startTime = DateUtil.beginOfMonth(date);
            endTime = DateUtil.endOfMonth(date);
        }else if(type == 3){
            //当季度
            startTime = DateUtil.beginOfQuarter(date);
            endTime = DateUtil.endOfQuarter(date);
        }else if(type == 4){
            //当年
            startTime = DateUtil.beginOfYear(date);
            endTime = DateUtil.endOfYear(date);
        }

        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("status","sum(actual_total) as actualTotal","sum(product_nums) as productNums");
        queryWrapper.between("pay_time", startTime, endTime);
        queryWrapper.eq("is_payed",1);//已支付
        queryWrapper.in("status",Arrays.asList(2, 3, 4, 5));
        queryWrapper.groupBy("status");
        List<Map<String, Object>> list1 = orderService.listMaps(queryWrapper);

        Map<String,Object> map1=new HashMap<>();
        for(Map<String, Object> map:list1){
            map1.put(String.valueOf((Integer)map.get("status")),map);
        }

        List<Integer> integers = Arrays.asList(2, 3, 4, 5);

        for(Integer s:integers){
            Map<String, Object> o = (Map<String, Object>)map1.get(String.valueOf(s));
            if(o == null){
                Map<String, Object> map2=new HashMap<>();
                map2.put("actualTotal",0);
                map2.put("productNums",0);
                map2.put("status",s);
                map1.put(String.valueOf(s),map2);
            }
        }

        rmap.put("orderStatistics",map1);

        /**
         * 统计退款信息
         */
        List<Order> list = orderService.lambdaQuery()
                .select(Order::getOrderNumber)
                .between(Order::getPayTime, startTime, endTime)
                .eq(Order::getIsPayed, 1)//已支付
                .in(Order::getStatus, Arrays.asList(2, 3, 4, 5)).list();

        List<String> collect = list.stream().map(o -> o.getOrderNumber()).collect(Collectors.toList());
        if(collect.isEmpty()){
            collect.add("-1");
        }
        QueryWrapper<OrderRefund> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.select("return_money_sts as returnMoneySts","sum(goods_num) as goodsNum","sum(refund_amount) as refundAmount");
        queryWrapper1.in("order_number",collect);
        queryWrapper1.groupBy("return_money_sts");
        List<Map<String, Object>> list2 = orderRefundService.listMaps(queryWrapper1);

        Map<String,Object> map3=new HashMap<>();
        for(Map<String, Object> map:list2){
            map3.put(String.valueOf((Integer)map.get("returnMoneySts")),map);
        }

        List<Integer> integers1 = Arrays.asList(0,1,-1);
        for(Integer s:integers1){
            Map<String, Object> o = (Map<String, Object>)map3.get(String.valueOf(s));
            if(o == null){
                Map<String, Object> map2=new HashMap<>();
                map2.put("goodsNum",0);
                map2.put("refundAmount",0);
                map2.put("returnMoneySts",s);
                map3.put(String.valueOf(s),map2);
            }
        }
        rmap.put("orderRefundStatistics",map3);

        /**
         * 查询订单的返利和销售奖金,按分类统计多少金额
         */
        List<String> strings = Arrays.asList(UserFundDetailEnum.TYPE_0.getValue(), UserFundDetailEnum.TYPE_1.getValue(), UserFundDetailEnum.TYPE_2.getValue(), UserFundDetailEnum.TYPE_5.getValue());
        QueryWrapper<UserFundDetail> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.select("type","sum(money) as money");
        queryWrapper2.in("order_number",collect);
        queryWrapper2.eq("category", UserFundDetailEnum.DISTRIBUTION_BONUS.getValue());
        queryWrapper2.in("type",strings);
        queryWrapper2.groupBy("type");
        List<Map<String, Object>> list3 = userFundDetailService.listMaps(queryWrapper2);

        Map<String,Object> map4=new HashMap<>();
        for(Map<String, Object> map:list3){
            map4.put(String.valueOf((String)map.get("type")),map);
        }
        for(String s:strings){
            Map<String, Object> o = (Map<String, Object>)map4.get(String.valueOf(s));
            if(o == null){
                Map<String, Object> map2=new HashMap<>();
                map2.put("money",0);
                map2.put("type",s);
                map4.put(String.valueOf(s),map2);
            }
        }
        rmap.put("orderRewardStatistics",map4);

        return ServerResponseEntity.success(rmap);
    }

    /**
     * 订单和奖励金额的统计导出
     * @param type
     * @param response
     * @throws IOException
     */
    @PreAuthorize("@pms.hasPermission('order:order:page')")
    @GetMapping("/exportOrderStatistics")
    public void exportOrderStatistics(Integer type, HttpServletResponse response) throws IOException {
        //Map<String,Object> rmap=new HashMap<>();
        if(type == null){
            type =0;
        }
        Date date = new Date();
        DateTime startTime=null;
        DateTime endTime=null;
        if(type == 0){
            //查询当天
            startTime = DateUtil.beginOfDay(date);
            endTime = DateUtil.endOfDay(date);
        }else if(type == 1){
            //当周
            startTime = DateUtil.beginOfWeek(date);
            endTime = DateUtil.endOfWeek(date);
        }else if(type == 2){
            //当月
            startTime = DateUtil.beginOfMonth(date);
            endTime = DateUtil.endOfMonth(date);
        }else if(type == 3){
            //当季度
            startTime = DateUtil.beginOfQuarter(date);
            endTime = DateUtil.endOfQuarter(date);
        }else if(type == 4){
            //当年
            startTime = DateUtil.beginOfYear(date);
            endTime = DateUtil.endOfYear(date);
        }

        Map<String, Object> rootMap = MapUtils.newHashMap();

        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("status","sum(actual_total) as actualTotal","sum(product_nums) as productNums");
        queryWrapper.between("pay_time", startTime, endTime);
        queryWrapper.eq("is_payed",1);//已支付
        queryWrapper.in("status",Arrays.asList(2, 3, 4, 5));
        queryWrapper.groupBy("status");
        List<Map<String, Object>> list1 = orderService.listMaps(queryWrapper);

        Map<String,Object> map1=new HashMap<>();
        for(Map<String, Object> map:list1){
            map1.put(String.valueOf((Integer)map.get("status")),map);
        }

        List<Integer> integers = Arrays.asList(2, 3, 4, 5);

        for(Integer s:integers){
            Map<String, Object> o = (Map<String, Object>)map1.get(String.valueOf(s));
            if(o == null){
                Map<String, Object> map2=new HashMap<>();
                map2.put("actualTotal",0);
                map2.put("productNums",0);
                map2.put("status",s);
                map1.put(String.valueOf(s),map2);
            }
        }

        //rmap.put("orderStatistics",map1);
        for(String key:map1.keySet()){
            Map<String,Object> o = (Map<String,Object>)map1.get(key);
            if(StringUtil.equals(key,"2")){
                rootMap.put("orderStatistics2productNums",o.get("productNums"));
                rootMap.put("orderStatistics2actualTotal",o.get("actualTotal"));
            }else if(StringUtil.equals(key,"3")){
                rootMap.put("orderStatistics3productNums",o.get("productNums"));
                rootMap.put("orderStatistics3actualTotal",o.get("actualTotal"));
            }else if(StringUtil.equals(key,"4")){
                rootMap.put("orderStatistics4productNums",o.get("productNums"));
                rootMap.put("orderStatistics4actualTotal",o.get("actualTotal"));
            }else if(StringUtil.equals(key,"5")){
                rootMap.put("orderStatistics5productNums",o.get("productNums"));
                rootMap.put("orderStatistics5actualTotal",o.get("actualTotal"));
            }else if(StringUtil.equals(key,"6")){
                rootMap.put("orderStatistics6productNums",o.get("productNums"));
                rootMap.put("orderStatistics6actualTotal",o.get("actualTotal"));
            }
        }

        /**
         * 统计退款信息
         */
        List<Order> list = orderService.lambdaQuery()
                .select(Order::getOrderNumber)
                .between(Order::getPayTime, startTime, endTime)
                .eq(Order::getIsPayed, 1)//已支付
                .in(Order::getStatus, Arrays.asList(2, 3, 4, 5)).list();

        List<String> collect = list.stream().map(o -> o.getOrderNumber()).collect(Collectors.toList());
        if(collect.isEmpty()){
            collect.add("-1");
        }
        QueryWrapper<OrderRefund> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.select("return_money_sts as returnMoneySts","sum(goods_num) as goodsNum","sum(refund_amount) as refundAmount");
        queryWrapper1.in("order_number",collect);
        queryWrapper1.groupBy("return_money_sts");
        List<Map<String, Object>> list2 = orderRefundService.listMaps(queryWrapper1);

        Map<String,Object> map3=new HashMap<>();
        for(Map<String, Object> map:list2){
            map3.put(String.valueOf((Integer)map.get("returnMoneySts")),map);
        }

        List<Integer> integers1 = Arrays.asList(0,1,-1);
        for(Integer s:integers1){
            Map<String, Object> o = (Map<String, Object>)map3.get(String.valueOf(s));
            if(o == null){
                Map<String, Object> map2=new HashMap<>();
                map2.put("goodsNum",0);
                map2.put("refundAmount",0);
                map2.put("returnMoneySts",s);
                map3.put(String.valueOf(s),map2);
            }
        }
        //rmap.put("orderRefundStatistics",map3);
        for(String key:map3.keySet()){
            Map<String,Object> o = (Map<String,Object>)map3.get(key);
            if(StringUtil.equals(key,"0")){
                rootMap.put("orderRefundStatistics0goodsNum",o.get("goodsNum"));
                rootMap.put("orderRefundStatistics0refundAmount",o.get("refundAmount"));
            }else if(StringUtil.equals(key,"1")){
                rootMap.put("orderRefundStatistics1goodsNum",o.get("goodsNum"));
                rootMap.put("orderRefundStatistics1refundAmount",o.get("refundAmount"));
            }else if(StringUtil.equals(key,"-1")){
                rootMap.put("orderRefundStatistics-1goodsNum",o.get("goodsNum"));
                rootMap.put("orderRefundStatistics-1refundAmount",o.get("refundAmount"));
            }
        }
        /**
         * 查询订单的返利和销售奖金,按分类统计多少金额
         */
        List<String> strings = Arrays.asList(UserFundDetailEnum.TYPE_0.getValue(), UserFundDetailEnum.TYPE_1.getValue(), UserFundDetailEnum.TYPE_2.getValue(), UserFundDetailEnum.TYPE_5.getValue());
        QueryWrapper<UserFundDetail> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.select("type","sum(money) as money");
        queryWrapper2.in("order_number",collect);
        queryWrapper2.eq("category", UserFundDetailEnum.DISTRIBUTION_BONUS.getValue());
        queryWrapper2.in("type",strings);
        queryWrapper2.groupBy("type");
        List<Map<String, Object>> list3 = userFundDetailService.listMaps(queryWrapper2);

        Map<String,Object> map4=new HashMap<>();
        for(Map<String, Object> map:list3){
            map4.put(String.valueOf((String)map.get("type")),map);
        }
        for(String s:strings){
            Map<String, Object> o = (Map<String, Object>)map4.get(String.valueOf(s));
            if(o == null){
                Map<String, Object> map2=new HashMap<>();
                map2.put("money",0);
                map2.put("type",s);
                map4.put(String.valueOf(s),map2);
            }
        }
        //rmap.put("orderRewardStatistics",map4);
        for(String key:map4.keySet()){
            Map<String,Object> o = (Map<String,Object>)map4.get(key);
            if(StringUtil.equals(key,"reward2YuanMoney")){
                rootMap.put("reward2YuanMoney",o.get("money"));
            }else if(StringUtil.equals(key,"level1")){
                rootMap.put("level1",o.get("money"));
            }else if(StringUtil.equals(key,"level2")){
                rootMap.put("level2",o.get("money"));
            }else if(StringUtil.equals(key,"level3")){
                rootMap.put("level3",o.get("money"));
            }
        }

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");

        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("导出订单和奖励统计", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

        ClassPathResource classPathResource = new ClassPathResource("excelTemplate/exportOrderStatistics.xlsx");

        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(classPathResource.getInputStream()).build();

        WriteSheet writeSheet = EasyExcel.writerSheet().build();

        //写入list
        //FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
        //excelWriter.fill(data(), fillConfig, writeSheet);
        //excelWriter.fill(data(), fillConfig, writeSheet);

        //写入map
        //map.put("text", "2019年10月9日13:28:28");
        //map.put("total", rmap);

        excelWriter.fill(rootMap, writeSheet);

        //填充完成
        excelWriter.finish();
    }

    /**
     * 查看分部业绩
     * @param param
     * @return
     */
    @PreAuthorize("@pms.hasPermission('order:order:page')")
    @GetMapping("/getVipLevel3UserPerformance")
    public ServerResponseEntity<Map<String,Object>> getVipLevel3UserPerformance(GetVipLevel3UserPerformanceParam param)  {
        if(StringUtil.isBlank(param.getVipLevel3User()) || param.getStartTime() == null || param.getEndTime() == null){
            return ServerResponseEntity.showFailMsg("参数不能为空");
        }

        String enableDistributionProdIds = this.getValueByConfig("enable_distribution_prod_ids");
        List<String> prodIds = Arrays.asList(StringUtils.split(enableDistributionProdIds, ","));


        //获取自己以下所有用户
        List<User>  list0=userService.getLowerLevel(param.getVipLevel3User(),new ArrayList<>());
        list0.add(userService.getById(param.getVipLevel3User()));//加上自己

        List<String> collect1 = list0.stream().map(u -> u.getUserId()).collect(Collectors.toList());

        //查询用户当前下单数量
        List<Order> list = orderService.lambdaQuery()
                .select(Order::getOrderNumber,Order::getProdName,Order::getActualTotal,Order::getActualTotal,Order::getStatus,Order::getUserId,Order::getPayType)
                .in(Order::getUserId, collect1)
                .eq(Order::getIsPayed,1)//已支付
                .between(Order::getPayTime,param.getStartTime(),param.getEndTime())
                .list();

        Map<String,Order> omap=new HashMap<>();
        for(Order order:list){
            omap.put(order.getOrderNumber(),order);
        }

        List<String> collect = list.stream().map(o -> o.getOrderNumber()).collect(Collectors.toList());

        //下单数量
        Integer orderQuantity=0;
        //退款数量
        Integer refundQuantity=0;

        //下单金额
        BigDecimal orderMoney=BigDecimal.ZERO;
        //退款金额
        BigDecimal refundMoney=BigDecimal.ZERO;

        //奖励金额
        BigDecimal rewardMoney=BigDecimal.ZERO;

        List<String> strings = Arrays.asList(UserFundDetailEnum.TYPE_0.getValue(), UserFundDetailEnum.TYPE_1.getValue(), UserFundDetailEnum.TYPE_2.getValue(), UserFundDetailEnum.TYPE_5.getValue());

        List<GetVipLevel3UserPerformanceVo> list6=new ArrayList<>();

        for(String orderNumber:collect){
            GetVipLevel3UserPerformanceVo vo=new GetVipLevel3UserPerformanceVo();
            Order order = omap.get(orderNumber);
            vo.setOrderNumber(order.getOrderNumber());
            vo.setProdName(order.getProdName());
            vo.setActualTotal(order.getActualTotal());
            vo.setPayType(order.getPayType());
            vo.setStatus(order.getStatus());

            User byId = userService.getById(order.getUserId());
            if(byId != null){
                vo.setUserNickName(byId.getNickName());
            }

            List<OrderItem> list1 = orderItemService.lambdaQuery()
                    .select(OrderItem::getOrderItemId,OrderItem::getProdCount,OrderItem::getProductTotalAmount)
                    .eq(OrderItem::getOrderNumber, orderNumber)
                    .in(OrderItem::getProdId, prodIds).list();
            //共下单了几个
            int sum1 = list1.stream().mapToInt(i -> i.getProdCount()).sum();
            Double sum2 = list1.stream().mapToDouble(i -> i.getProductTotalAmount()).sum();
            orderMoney = orderMoney.add(new BigDecimal(sum2.toString()));
            orderQuantity = orderQuantity+sum1;

            vo.setOrderQuantity(sum1);
            vo.setOrderMoney(new BigDecimal(sum2));
            for(OrderItem item:list1){
                List<OrderRefund> list2 = orderRefundService.lambdaQuery()
                        .select(OrderRefund::getGoodsNum,OrderRefund::getRefundAmount)
                        .eq(OrderRefund::getOrderItemId, item.getOrderItemId())
                        .eq(OrderRefund::getReturnMoneySts, 1)//退款成功的
                        .list();

                //本个子订单共退款成功了几单
                int sum = list2.stream().mapToInt(r -> r.getGoodsNum()).sum();
                refundQuantity = refundQuantity + sum;

                BigDecimal reduce = list2.stream().map(r -> r.getRefundAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
                refundMoney = refundMoney.add(reduce);

                vo.setRefundQuantity(sum);
                vo.setRefundMoney(reduce);
            }


            List<UserFundDetail> list2 = userFundDetailService.lambdaQuery()
                    .select(UserFundDetail::getType,UserFundDetail::getMoney)
                    .eq(UserFundDetail::getOrderNumber, orderNumber)
                    .eq(UserFundDetail::getCategory, UserFundDetailEnum.DISTRIBUTION_BONUS.getValue())
                    .in(UserFundDetail::getType, strings).list();

            //本比订单总奖励金额
            BigDecimal reduce = list2.stream().map(f -> f.getMoney()).reduce(BigDecimal.ZERO, BigDecimal::add);
            rewardMoney = rewardMoney.add(reduce);

            //一级奖励金额
            BigDecimal type0 = list2.stream().filter(f -> StringUtil.equals(f.getType(),UserFundDetailEnum.TYPE_0.getValue())).map(f -> f.getMoney()).reduce(BigDecimal.ZERO, BigDecimal::add);

            //二级奖励金额
            BigDecimal type1 = list2.stream().filter(f -> StringUtil.equals(f.getType(),UserFundDetailEnum.TYPE_1.getValue())).map(f -> f.getMoney()).reduce(BigDecimal.ZERO, BigDecimal::add);

            //三级奖励金额
            BigDecimal type2 = list2.stream().filter(f -> StringUtil.equals(f.getType(),UserFundDetailEnum.TYPE_2.getValue())).map(f -> f.getMoney()).reduce(BigDecimal.ZERO, BigDecimal::add);

            //老上级奖励
            BigDecimal type5 = list2.stream().filter(f -> StringUtil.equals(f.getType(),UserFundDetailEnum.TYPE_5.getValue())).map(f -> f.getMoney()).reduce(BigDecimal.ZERO, BigDecimal::add);

            vo.setLevel1(type0);
            vo.setLevel2(type1);
            vo.setLevel3(type2);
            vo.setReward2YuanMoney(type5);

            list6.add(vo);
        }

        Map<String,Object> rmap=new HashMap<>();
        rmap.put("orderQuantity",orderQuantity);
        rmap.put("refundQuantity",refundQuantity);
        rmap.put("orderMoney",orderMoney);
        rmap.put("refundMoney",refundMoney);
        rmap.put("rewardMoney",rewardMoney);

        rmap.put("orderList",list6);

        return ServerResponseEntity.success(rmap);
    }


    /**
     * 获取配置项
     * @param key
     * @return
     */
    public String  getValueByConfig(String key) {
        List<String> param_value = jdbcTemplate.query("select param_value from tz_sys_config where param_key = ? ", new RowMapper<String>() {
            @Override
            public String mapRow(ResultSet rs, int rowNum) throws SQLException {
                return rs.getString("param_value");
            }
        }, key);

        if(param_value.isEmpty()){
            return null;
        }else{
            return param_value.get(0);
        }
    }

    /**
     * 分部业绩导出
     * @param param
     * @param response
     * @throws IOException
     */
    @PreAuthorize("@pms.hasPermission('order:order:page')")
    @GetMapping("/exportVipLevel3UserPerformance")
    public void exportVipLevel3UserPerformance(GetVipLevel3UserPerformanceParam param, HttpServletResponse response) throws IOException {
        if(StringUtil.isBlank(param.getVipLevel3User()) || param.getStartTime() == null || param.getEndTime() == null){
            throw new RuntimeException("参数不能为空");
        }

        String enableDistributionProdIds = this.getValueByConfig("enable_distribution_prod_ids");
        List<String> prodIds = Arrays.asList(StringUtils.split(enableDistributionProdIds, ","));


        //获取自己以下所有用户
        List<User>  list0=userService.getLowerLevel(param.getVipLevel3User(),new ArrayList<>());
        list0.add(userService.getById(param.getVipLevel3User()));//加上自己

        List<String> collect1 = list0.stream().map(u -> u.getUserId()).collect(Collectors.toList());

        //查询用户当前下单数量
        List<Order> list = orderService.lambdaQuery()
                .select(Order::getOrderNumber,Order::getProdName,Order::getActualTotal,Order::getActualTotal,Order::getStatus,Order::getUserId,Order::getPayType)
                .in(Order::getUserId, collect1)
                .eq(Order::getIsPayed,1)//已支付
                .between(Order::getPayTime,param.getStartTime(),param.getEndTime())
                .list();

        Map<String,Order> omap=new HashMap<>();
        for(Order order:list){
            omap.put(order.getOrderNumber(),order);
        }

        List<String> collect = list.stream().map(o -> o.getOrderNumber()).collect(Collectors.toList());

        //下单数量
        Integer orderQuantity=0;
        //退款数量
        Integer refundQuantity=0;

        //下单金额
        BigDecimal orderMoney=BigDecimal.ZERO;
        //退款金额
        BigDecimal refundMoney=BigDecimal.ZERO;

        //奖励金额
        BigDecimal rewardMoney=BigDecimal.ZERO;

        List<String> strings = Arrays.asList(UserFundDetailEnum.TYPE_0.getValue(), UserFundDetailEnum.TYPE_1.getValue(), UserFundDetailEnum.TYPE_2.getValue(), UserFundDetailEnum.TYPE_5.getValue());

        List<GetVipLevel3UserPerformanceVo> list6=new ArrayList<>();

        for(String orderNumber:collect){
            GetVipLevel3UserPerformanceVo vo=new GetVipLevel3UserPerformanceVo();
            Order order = omap.get(orderNumber);
            vo.setOrderNumber(order.getOrderNumber());
            vo.setProdName(order.getProdName());
            vo.setActualTotal(order.getActualTotal());

            vo.setPayType(order.getPayType());
            vo.setStatus(order.getStatus());

            if(order.getPayType() == 0){
                vo.setPayTypeName("手动代付");
            }else if(order.getPayType() == 1){
                vo.setPayTypeName("微信支付");
            }else if(order.getPayType() == 2){
                vo.setPayTypeName("支付宝");
            }

            if(order.getStatus() == 1){
                vo.setStatusName("待付款");
            }else if(order.getStatus() == 2){
                vo.setStatusName("待发货");
            }else if(order.getStatus() == 3){
                vo.setStatusName("待收货");
            }else if(order.getStatus() == 4){
                vo.setStatusName("待评价");
            }else if(order.getStatus() == 5){
                vo.setStatusName("成功");
            }else if(order.getStatus() == 6){
                vo.setStatusName("失败");
            }

            User byId = userService.getById(order.getUserId());
            if(byId != null){
                vo.setUserNickName(byId.getNickName());
            }

            List<OrderItem> list1 = orderItemService.lambdaQuery()
                    .select(OrderItem::getOrderItemId,OrderItem::getProdCount,OrderItem::getProductTotalAmount)
                    .eq(OrderItem::getOrderNumber, orderNumber)
                    .in(OrderItem::getProdId, prodIds).list();
            //共下单了几个
            int sum1 = list1.stream().mapToInt(i -> i.getProdCount()).sum();
            Double sum2 = list1.stream().mapToDouble(i -> i.getProductTotalAmount()).sum();
            orderMoney = orderMoney.add(new BigDecimal(sum2.toString()));
            orderQuantity = orderQuantity+sum1;

            vo.setOrderQuantity(sum1);
            vo.setOrderMoney(new BigDecimal(sum2));
            for(OrderItem item:list1){
                List<OrderRefund> list2 = orderRefundService.lambdaQuery()
                        .select(OrderRefund::getGoodsNum,OrderRefund::getRefundAmount)
                        .eq(OrderRefund::getOrderItemId, item.getOrderItemId())
                        .eq(OrderRefund::getReturnMoneySts, 1)//退款成功的
                        .list();

                //本个子订单共退款成功了几单
                int sum = list2.stream().mapToInt(r -> r.getGoodsNum()).sum();
                refundQuantity = refundQuantity + sum;

                BigDecimal reduce = list2.stream().map(r -> r.getRefundAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
                refundMoney = refundMoney.add(reduce);

                vo.setRefundQuantity(sum);
                vo.setRefundMoney(reduce);
            }


            List<UserFundDetail> list2 = userFundDetailService.lambdaQuery()
                    .select(UserFundDetail::getType,UserFundDetail::getMoney)
                    .eq(UserFundDetail::getOrderNumber, orderNumber)
                    .eq(UserFundDetail::getCategory, UserFundDetailEnum.DISTRIBUTION_BONUS.getValue())
                    .in(UserFundDetail::getType, strings).list();

            //本比订单总奖励金额
            BigDecimal reduce = list2.stream().map(f -> f.getMoney()).reduce(BigDecimal.ZERO, BigDecimal::add);
            rewardMoney = rewardMoney.add(reduce);

            //一级奖励金额
            BigDecimal type0 = list2.stream().filter(f -> StringUtil.equals(f.getType(),UserFundDetailEnum.TYPE_0.getValue())).map(f -> f.getMoney()).reduce(BigDecimal.ZERO, BigDecimal::add);

            //二级奖励金额
            BigDecimal type1 = list2.stream().filter(f -> StringUtil.equals(f.getType(),UserFundDetailEnum.TYPE_1.getValue())).map(f -> f.getMoney()).reduce(BigDecimal.ZERO, BigDecimal::add);

            //三级奖励金额
            BigDecimal type2 = list2.stream().filter(f -> StringUtil.equals(f.getType(),UserFundDetailEnum.TYPE_2.getValue())).map(f -> f.getMoney()).reduce(BigDecimal.ZERO, BigDecimal::add);

            //老上级奖励
            BigDecimal type5 = list2.stream().filter(f -> StringUtil.equals(f.getType(),UserFundDetailEnum.TYPE_5.getValue())).map(f -> f.getMoney()).reduce(BigDecimal.ZERO, BigDecimal::add);

            vo.setLevel1(type0);
            vo.setLevel2(type1);
            vo.setLevel3(type2);
            vo.setReward2YuanMoney(type5);

            list6.add(vo);
        }

        Map<String,Object> rmap=new HashMap<>();
        rmap.put("orderQuantity",orderQuantity);
        rmap.put("refundQuantity",refundQuantity);
        rmap.put("orderMoney",orderMoney);
        rmap.put("refundMoney",refundMoney);
        rmap.put("rewardMoney",rewardMoney);

        //rmap.put("orderList",list6);

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");

        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("分部业绩", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

        ClassPathResource classPathResource = new ClassPathResource("excelTemplate/exportVipLevel3UserPerformance.xlsx");

        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(classPathResource.getInputStream()).build();

        WriteSheet writeSheet = EasyExcel.writerSheet().build();

        //写入list
        FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
        excelWriter.fill(list6, fillConfig, writeSheet);
        //excelWriter.fill(data(), fillConfig, writeSheet);

        //写入map
        //map.put("text", "2019年10月9日13:28:28");
        //map.put("total", rmap);

        excelWriter.fill(rmap, writeSheet);
        //填充完成
        excelWriter.finish();
    }


    /**
     * 分部用户奖励统计
     * @param param
     * @return
     */
    @PreAuthorize("@pms.hasPermission('order:order:page')")
    @GetMapping("/branchUserCashOutStatistics")
    public ServerResponseEntity<Map<String,Object>> branchUserCashOutStatistics(GetVipLevel3UserPerformanceParam param)  {
        if(StringUtil.isBlank(param.getVipLevel3User()) ){
            return ServerResponseEntity.showFailMsg("参数不能为空");
        }
        boolean time= param.getStartTime() != null && param.getEndTime() != null;
        //获取自己以下所有用户

        List<User>  list0=userService.getLowerLevel(param.getVipLevel3User(),new ArrayList<>());
        list0.add(userService.getById(param.getVipLevel3User()));//加上自己

        List<String> collect1 = list0.stream().map(u -> u.getUserId()).collect(Collectors.toList());

        //查询时间段内订单
        List<Order> list = orderService.lambdaQuery()
                .select(Order::getOrderNumber)
                .in(Order::getUserId, collect1)
                .eq(Order::getIsPayed,1)//已支付
                .between(time,Order::getPayTime,param.getStartTime(),param.getEndTime())
                .list();
        List<String> collect = list.stream().map(o -> o.getOrderNumber()).collect(Collectors.toList());
        if(collect.isEmpty()){
            return ServerResponseEntity.showFailMsg("周期内无订单");
        }

        List<String> strings = Arrays.asList(UserFundDetailEnum.TYPE_0.getValue(), UserFundDetailEnum.TYPE_1.getValue(), UserFundDetailEnum.TYPE_2.getValue(), UserFundDetailEnum.TYPE_5.getValue());

        List<String> stringsAll = Arrays.asList(UserFundDetailEnum.TYPE_0.getValue(), UserFundDetailEnum.TYPE_1.getValue(), UserFundDetailEnum.TYPE_2.getValue(), UserFundDetailEnum.TYPE_3.getValue(), UserFundDetailEnum.TYPE_4.getValue(), UserFundDetailEnum.TYPE_5.getValue());

        List<BranchUserCashOutStatisticsVo> list4=new ArrayList<>();
        for(User user:list0){
            User byId = userService.getById(user.getUserId());

            BranchUserCashOutStatisticsVo vo=new BranchUserCashOutStatisticsVo();
            vo.setUid(byId.getUserId());
            vo.setNickName(byId.getNickName());
            vo.setDistributionBonus(byId.getDistributionBonus());

            List<UserFundDetail> list1 = userFundDetailService.lambdaQuery()
                    .select(UserFundDetail::getMoney)
                    .eq(UserFundDetail::getUid, user.getUserId())
                    .eq(UserFundDetail::getCategory, UserFundDetailEnum.DISTRIBUTION_BONUS.getValue())
                    .in(UserFundDetail::getType, strings)
                    .in(UserFundDetail::getOrderNumber, collect)
                    .list();

            //用户时间段总奖励金额
            BigDecimal reduce = list1.stream().map(f -> f.getMoney()).reduce(BigDecimal.ZERO, BigDecimal::add);
            vo.setRewardMoney(reduce);

            List<UserCashOut> list2 = userCashOutService.lambdaQuery()
                    .select(UserCashOut::getId,UserCashOut::getCashMoney)
                    .between(time,UserCashOut::getCreateTime, param.getStartTime(), param.getEndTime())
                    .eq(UserCashOut::getUserAccountTable, "tz_user")
                    .eq(UserCashOut::getUserAccountTableField, "distribution_bonus")
                    .eq(UserCashOut::getUserAccountTableId, user.getUserId())
                    .in(UserCashOut::getState, Arrays.asList(1))
                    .list();

            //提现成功总金额
            BigDecimal reduce1 = list2.stream().map(c -> c.getCashMoney()).reduce(BigDecimal.ZERO, BigDecimal::add);

            vo.setCashOutMoney(reduce1);

            //查询所有提现
            List<UserCashOut> list6 = userCashOutService.lambdaQuery()
                    .select(UserCashOut::getId)
                    .between(time,UserCashOut::getCreateTime, param.getStartTime(), param.getEndTime())
                    .eq(UserCashOut::getUserAccountTable, "tz_user")
                    .eq(UserCashOut::getUserAccountTableField, "distribution_bonus")
                    .eq(UserCashOut::getUserAccountTableId, user.getUserId())
                    .list();

            List<String> collect2 = list6.stream().map(c -> String.valueOf(c.getId())).collect(Collectors.toList());

            List<String> strings1 = new ArrayList<>(collect);
            strings1.addAll(collect2);

            //查看时间段内用户所涉及的资金明细记录

            List<UserFundDetail> list3 = userFundDetailService.lambdaQuery()
                    .eq(UserFundDetail::getUid, user.getUserId())
                    .eq(UserFundDetail::getCategory, UserFundDetailEnum.DISTRIBUTION_BONUS.getValue())
                    .in(UserFundDetail::getType, stringsAll)
                    .in(UserFundDetail::getOrderNumber, strings1)
                    .orderByDesc(UserFundDetail::getCreateTime,UserFundDetail::getId)
                    .list();
            vo.setFundDetails(list3);
            list4.add(vo);
        }

        //分部用户账号中现有总的奖励金额
        BigDecimal distributionBonus = list4.stream().filter(u -> u.getDistributionBonus() != null).map(u -> u.getDistributionBonus()).reduce(BigDecimal.ZERO, BigDecimal::add);

        //分部时间段内订单生成的奖励总金额
        BigDecimal rewardMoney = list4.stream().filter(u -> u.getRewardMoney() != null).map(u -> u.getRewardMoney()).reduce(BigDecimal.ZERO, BigDecimal::add);

        //分部用户时间段内体现完成的总金额
        BigDecimal cashOutMoney = list4.stream().filter(u -> u.getCashOutMoney() != null).map(u -> u.getCashOutMoney()).reduce(BigDecimal.ZERO, BigDecimal::add);

        Map<String,Object> rmap=new HashMap<>();
        rmap.put("distributionBonus",distributionBonus);
        rmap.put("rewardMoney",rewardMoney);
        rmap.put("cashOutMoney",cashOutMoney);
        rmap.put("list",list4);

        return ServerResponseEntity.success(rmap);
    }

    /**
     * 导出分部用户奖励统计
     * @param param
     * @return
     */
    @PreAuthorize("@pms.hasPermission('order:order:page')")
    @GetMapping("/exportBranchUserCashOutStatistics")
    public void exportBranchUserCashOutStatistics(GetVipLevel3UserPerformanceParam param, HttpServletResponse response) throws IOException {
        if(StringUtil.isBlank(param.getVipLevel3User()) ){
            throw new RuntimeException("参数不能为空");
        }
        boolean time= param.getStartTime() != null && param.getEndTime() != null;
        //获取自己以下所有用户

        List<User>  list0=userService.getLowerLevel(param.getVipLevel3User(),new ArrayList<>());
        list0.add(userService.getById(param.getVipLevel3User()));//加上自己

        List<String> collect1 = list0.stream().map(u -> u.getUserId()).collect(Collectors.toList());

        //查询时间段内订单
        List<Order> list = orderService.lambdaQuery()
                .select(Order::getOrderNumber)
                .in(Order::getUserId, collect1)
                .eq(Order::getIsPayed,1)//已支付
                .between(time,Order::getPayTime,param.getStartTime(),param.getEndTime())
                .list();
        List<String> collect = list.stream().map(o -> o.getOrderNumber()).collect(Collectors.toList());
        if(collect.isEmpty()){
            throw new RuntimeException("周期内无订单");
        }

        List<String> strings = Arrays.asList(UserFundDetailEnum.TYPE_0.getValue(), UserFundDetailEnum.TYPE_1.getValue(), UserFundDetailEnum.TYPE_2.getValue(), UserFundDetailEnum.TYPE_5.getValue());

        List<String> stringsAll = Arrays.asList(UserFundDetailEnum.TYPE_0.getValue(), UserFundDetailEnum.TYPE_1.getValue(), UserFundDetailEnum.TYPE_2.getValue(), UserFundDetailEnum.TYPE_3.getValue(), UserFundDetailEnum.TYPE_4.getValue(), UserFundDetailEnum.TYPE_5.getValue());

        List<BranchUserCashOutStatisticsVo> list4=new ArrayList<>();
        for(User user:list0){
            User byId = userService.getById(user.getUserId());

            BranchUserCashOutStatisticsVo vo=new BranchUserCashOutStatisticsVo();
            vo.setUid(byId.getUserId());
            vo.setNickName(byId.getNickName());
            vo.setDistributionBonus(byId.getDistributionBonus());

            List<UserFundDetail> list1 = userFundDetailService.lambdaQuery()
                    .select(UserFundDetail::getMoney)
                    .eq(UserFundDetail::getUid, user.getUserId())
                    .eq(UserFundDetail::getCategory, UserFundDetailEnum.DISTRIBUTION_BONUS.getValue())
                    .in(UserFundDetail::getType, strings)
                    .in(UserFundDetail::getOrderNumber, collect)
                    .list();

            //用户时间段总奖励金额
            BigDecimal reduce = list1.stream().map(f -> f.getMoney()).reduce(BigDecimal.ZERO, BigDecimal::add);
            vo.setRewardMoney(reduce);

            List<UserCashOut> list2 = userCashOutService.lambdaQuery()
                    .select(UserCashOut::getId,UserCashOut::getCashMoney)
                    .between(time,UserCashOut::getCreateTime, param.getStartTime(), param.getEndTime())
                    .eq(UserCashOut::getUserAccountTable, "tz_user")
                    .eq(UserCashOut::getUserAccountTableField, "distribution_bonus")
                    .eq(UserCashOut::getUserAccountTableId, user.getUserId())
                    .in(UserCashOut::getState, Arrays.asList(1))
                    .list();

            //提现成功总金额
            BigDecimal reduce1 = list2.stream().map(c -> c.getCashMoney()).reduce(BigDecimal.ZERO, BigDecimal::add);

            vo.setCashOutMoney(reduce1);

            //查询所有提现
            List<UserCashOut> list6 = userCashOutService.lambdaQuery()
                    .select(UserCashOut::getId)
                    .between(time,UserCashOut::getCreateTime, param.getStartTime(), param.getEndTime())
                    .eq(UserCashOut::getUserAccountTable, "tz_user")
                    .eq(UserCashOut::getUserAccountTableField, "distribution_bonus")
                    .eq(UserCashOut::getUserAccountTableId, user.getUserId())
                    .list();

            List<String> collect2 = list6.stream().map(c -> String.valueOf(c.getId())).collect(Collectors.toList());

            List<String> strings1 = new ArrayList<>(collect);
            strings1.addAll(collect2);

            //查看时间段内用户所涉及的资金明细记录

            List<UserFundDetail> list3 = userFundDetailService.lambdaQuery()
                    .eq(UserFundDetail::getUid, user.getUserId())
                    .eq(UserFundDetail::getCategory, UserFundDetailEnum.DISTRIBUTION_BONUS.getValue())
                    .in(UserFundDetail::getType, stringsAll)
                    .in(UserFundDetail::getOrderNumber, strings1)
                    .orderByDesc(UserFundDetail::getCreateTime,UserFundDetail::getId)
                    .list();
            vo.setFundDetails(list3);
            list4.add(vo);
        }

        //分部用户账号中现有总的奖励金额
        BigDecimal distributionBonus = list4.stream().filter(u -> u.getDistributionBonus() != null).map(u -> u.getDistributionBonus()).reduce(BigDecimal.ZERO, BigDecimal::add);

        //分部时间段内订单生成的奖励总金额
        BigDecimal rewardMoney = list4.stream().filter(u -> u.getRewardMoney() != null).map(u -> u.getRewardMoney()).reduce(BigDecimal.ZERO, BigDecimal::add);

        //分部用户时间段内体现完成的总金额
        BigDecimal cashOutMoney = list4.stream().filter(u -> u.getCashOutMoney() != null).map(u -> u.getCashOutMoney()).reduce(BigDecimal.ZERO, BigDecimal::add);

        Map<String,Object> rmap=new HashMap<>();
        rmap.put("distributionBonus",distributionBonus);
        rmap.put("rewardMoney",rewardMoney);
        rmap.put("cashOutMoney",cashOutMoney);
        //rmap.put("list",list4);


        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");

        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("分部用户奖励统计", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

        ClassPathResource classPathResource = new ClassPathResource("excelTemplate/exportBranchUserCashOutStatistics.xlsx");

        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(classPathResource.getInputStream()).build();

        WriteSheet writeSheet = EasyExcel.writerSheet().build();

        //写入list
        FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
        excelWriter.fill(list4, fillConfig, writeSheet);
        //excelWriter.fill(data(), fillConfig, writeSheet);

        //写入map
        //map.put("text", "2019年10月9日13:28:28");
        //map.put("total", rmap);

        excelWriter.fill(rmap, writeSheet);
        //填充完成
        excelWriter.finish();
    }
}
